﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using KDS.Mes.Mes.Parts.Dtos;
using KDS.Mes.Authorization;
using KDS.Mes.Dto;
using KDS.Mes.Mes.AlcCodes;
using KDS.Mes.Mes.SeatPositions;
using Abp.UI;
using KDS.Mes.Mes.Styles;
using KDS.Mes.Mes.Cartypes;

namespace KDS.Mes.Mes.Parts
{
    /// <summary>
    /// 零件信息服务实现
    /// </summary>
    [AbpAuthorize(AppPermissions.Pages_Bom_Parts)]
    public class PartAppService : MesAppServiceBase, IPartAppService
    {
        private readonly IRepository<Part, int> _partRepository;
        private readonly IPartListExcelExporter _partListExcelExporter;
        private readonly PartManage _partManage;
        private readonly IRepository<AlcCode, int> _alcCodeRepository;
        private readonly IRepository<SeatPosition, int> _seatPositionRepository;
        private readonly IRepository<Style, int> _styleRepository;
        private readonly IRepository<Cartype, int> _cartypeRepository;
        /// <summary>
        /// 构造方法
        /// </summary>
        public PartAppService(
            IRepository<Part, int> partRepository,
            PartManage partManage,
            IPartListExcelExporter partListExcelExporter,
            IRepository<AlcCode, int> alcCodeRepository,
            IRepository<SeatPosition, int> seatPositionRepository,
             IRepository<Style, int> styleRepository,
            IRepository<Cartype, int> cartypeRepository
  )
        {
            _partRepository = partRepository;
            _partManage = partManage;
            _partListExcelExporter = partListExcelExporter;
            _alcCodeRepository = alcCodeRepository;
            _seatPositionRepository = seatPositionRepository;
            _styleRepository = styleRepository;
            _cartypeRepository = cartypeRepository;
        }

        #region 零件信息管理

        public PagedResultDto<PartListDto> GetPagedParts(GetPartInput input)
        {
            ////初步过滤
            var query = from part in _partRepository.GetAll().WhereIf(input.SeatPositions[0].ToString() != "0", u => input.SeatPositions.Contains(u.SeatPositionId))
                        join alc in _alcCodeRepository.GetAll().WhereIf(!input.AlcCode.IsNullOrEmpty(), u => u.ALCCode == input.AlcCode) on part.AlcCodeId equals alc.Id
                        join st in _styleRepository.GetAll().WhereIf(!input.StyleId.IsNullOrEmpty(), u => u.Id.ToString() == input.StyleId) on alc.StyleId equals st.Id
                        join ct in _cartypeRepository.GetAll().WhereIf(!input.CartypeId.IsNullOrEmpty(), u => u.Id.ToString() == input.CartypeId) on st.CartypeId equals ct.Id
                        select new
                        {
                            part
                        };
            //排序
            query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(x => x.part.Id) : query.OrderByDescending(t => t.part.CreationTime);
            //获取总数
            var tasksCount = query.Count();
            //默认的分页方式
            //var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            //ABP提供了扩展方法PageBy分页方式
            var taskList = query.PageBy(input).ToList();

            return new PagedResultDto<PartListDto>(
             tasksCount,
             taskList.Select(item =>
             {
                 var dto = item.part.MapTo<PartListDto>();
                 return dto;
             }).ToList());




            ////初步过滤
            //var query = _partRepository.GetAll();
            ////排序
            //query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(x => x.Id) : query.OrderByDescending(t => t.CreationTime);
            ////获取总数
            //var tasksCount = query.Count();
            ////默认的分页方式
            ////var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();
            ////ABP提供了扩展方法PageBy分页方式
            //var taskList = query.PageBy(input).ToList();
            //return new PagedResultDto<PartListDto>(tasksCount, taskList.MapTo<List<PartListDto>>());
        }

        /// <summary>
        /// 根据查询条件获取零件信息分页列表
        /// </summary>
        public async Task<PagedResultDto<PartListDto>> GetPagedPartsAsync(GetPartInput input)
        {

            var query = _partRepository.GetAll();
            //TODO:根据传入的参数添加过滤条件

            var partCount = await query.CountAsync();

            var parts = await query
            .OrderBy(input.Sorting)
            .PageBy(input)
            .ToListAsync();

            var partListDtos = parts.MapTo<List<PartListDto>>();
            return new PagedResultDto<PartListDto>(
            partCount,
            partListDtos
            );
        }

        /// <summary>
        /// 通过Id获取零件信息信息进行编辑或修改 
        /// </summary>
        public async Task<GetPartForEditOutput> GetPartForEditAsync(NullableIdDto<int> input)
        {
            var output = new GetPartForEditOutput();

            PartEditDto partEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _partRepository.GetAsync(input.Id.Value);
                partEditDto = entity.MapTo<PartEditDto>();
            }
            else
            {
                partEditDto = new PartEditDto();
            }

            output.Part = partEditDto;
            output.AlcCodes = _alcCodeRepository.GetAllList()
              .Select(c => new ComboboxItemDto(c.Id.ToString(), c.ALCCode) { IsSelected = output.Part.AlcCodeId == c.Id })
              .ToList();
            output.SeatPositions = _seatPositionRepository.GetAllList()
              .Select(c => new ComboboxItemDto(c.Id.ToString(), c.SeatPositionName) { IsSelected = output.Part.SeatPositionId == c.Id })
              .ToList();
            return output;
        }


        /// <summary>
        /// 通过指定id获取零件信息ListDto信息
        /// </summary>
        public async Task<PartListDto> GetPartByIdAsync(EntityDto<int> input)
        {
            var entity = await _partRepository.GetAsync(input.Id);

            return entity.MapTo<PartListDto>();
        }







        /// <summary>
        /// 新增或更改零件信息
        /// </summary>
        public async Task CreateOrUpdatePartAsync(CreateOrUpdatePartInput input)
        {
            if (input.PartEditDto.Id.HasValue)
            {
                await UpdatePartAsync(input.PartEditDto);
            }
            else
            {
                await CreatePartAsync(input.PartEditDto);
            }
        }

        /// <summary>
        /// 新增零件信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_Parts_Create)]
        public virtual async Task<PartEditDto> CreatePartAsync(PartEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增
            await CheckPartIfAlreadyExists(input);
            var entity = input.MapTo<Part>();

            entity = await _partRepository.InsertAsync(entity);
            return entity.MapTo<PartEditDto>();
        }

        /// <summary>
        /// 编辑零件信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_Parts_Edit)]
        public virtual async Task UpdatePartAsync(PartEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新
            await CheckPartIfAlreadyExists(input);
            var entity = await _partRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _partRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除零件信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_Parts_Delete)]
        public async Task DeletePartAsync(EntityDto<int> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _partRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除零件信息
        /// </summary>
        [AbpAuthorize(AppPermissions.Pages_Bom_Parts_Delete)]
        public async Task BatchDeletePartAsync(List<int> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _partRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        private async Task CheckPartIfAlreadyExists(PartEditDto input)
        {
            var existingPart = await _partRepository.GetAll()
                .FirstOrDefaultAsync(l => l.AlcCodeId == input.AlcCodeId && l.SeatPositionId == input.SeatPositionId);
            if (existingPart == null)
            {
                return;
            }
            if (input.Id != null && existingPart.Id == input.Id)
            {
                return;
            }
            throw new UserFriendlyException(L("ThisPartAlreadyExists"));
        }

        #endregion


        #region 零件信息的Excel导出功能


        public async Task<FileDto> GetPartToExcel()
        {
            var entities = await _partRepository.GetAll().ToListAsync();

            var dtos = entities.MapTo<List<PartListDto>>();

            var fileDto = _partListExcelExporter.ExportPartToFile(dtos);



            return fileDto;
        }


        #endregion










    }
}
